package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.Category;
import com.ruoyi.system.domain.TbComingOutLog;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.mapper.CategoryMapper;
import com.ruoyi.system.mapper.ComingOutLogMapper;
import com.ruoyi.system.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private ComingOutLogMapper logMapper;
    // 添加分类缓存
    private Map<Long, Category> categoryCache = new ConcurrentHashMap<>();

    // 获取分类树
    @Override
    public List<Category> getCategoryTree() {
        List<Category> allCategories = categoryMapper.selectList(new QueryWrapper<Category>()
                .eq("del_flag", "0")
                .orderByAsc("parent_id", "id")
        );
        return buildTree(allCategories);
    }
    // 获取分类（带缓存）
    @Override
    public Category getCategoryById(Long id) {
        if (id == null) return null;

        // 从缓存获取
        Category category = categoryCache.get(id);
        if (category != null) return category;

        // 缓存中没有则查询数据库
        category = categoryMapper.selectById(id);
        if (category != null) {
            categoryCache.put(id, category);
        }
        return category;
    }

    // 根据ID获取分类
//    @Override
//    public Category getCategoryById(Long id) {
//        return categoryMapper.selectOne(new QueryWrapper<Category>()
//                .eq("id", id)
//                .eq("del_flag", "0")
//        );
//    }

    // 新增分类
    @Override
    @Transactional
    public void addCategory(Category category) {
        // 校验分类名称唯一性
        validateCategoryNameUnique(category.getName(), category.getParentId());

        // 设置层级
        if (category.getParentId().equals(0L)) {
            category.setLevel(1);
        } else {
            Category parent = getCategoryById(category.getParentId());
            category.setLevel(parent.getLevel() + 1);
        }

        categoryMapper.insert(category);
    }

    // 更新分类
    @Override
    @Transactional
    public void updateCategory(Category category) {
        Category existing = getCategoryById(category.getId());
        if (!existing.getName().equals(category.getName())) {
            validateCategoryNameUnique(category.getName(), category.getParentId());
        }
        categoryMapper.updateById(category);
    }

    // 删除分类（逻辑删除）
    @Override
    @Transactional
    public void deleteCategory(Long id) {
        // 检查是否存在子分类
        if (hasChildren(id)) {
            throw new RuntimeException("存在子分类，无法删除");
        }

        // 逻辑删除
        Category category = new Category();
        category.setId(id);
        category.setUpdateTime(LocalDateTime.now());
        categoryMapper.deleteById(category);
    }

    @Override
    public void handleOperation(OperationVO vo) {
        List<OperationVO.OperationItemVO> items = vo.getOperations();
        for (OperationVO.OperationItemVO item : items) {

            Long categoryId = Long.parseLong(item.getCategoryId());

            Category category = getCategoryById(categoryId);
            if (category == null) {
                throw new RuntimeException("分类不存在");
            }
            int newsurplusCount = category.getSurplusCount() + item.getInQuantity()-item.getOutQuantity();
            if (newsurplusCount < 0) {
                throw new RuntimeException("库存不足");
            }
            int surplusCount = category.getSurplusCount() + item.getInQuantity();
            //进库
            if (item.getInQuantity() >0) {
                TbComingOutLog log = new TbComingOutLog();
                log.setCategoryId(categoryId);
                log.setOperationType(1);
                log.setOperationBeforeCount(category.getSurplusCount());
                log.setOperationNum(item.getInQuantity());
                log.setOperationAfterCount(surplusCount);
                log.setCreateBy("admin");
                log.setCreateTime(LocalDateTime.now());
                logMapper.insert(log);
            }
            if (item.getOutQuantity() >0) { //出库
                TbComingOutLog log = new TbComingOutLog();
                log.setCategoryId(categoryId);
                log.setOperationType(0);
                log.setOperationBeforeCount(surplusCount);
                log.setOperationNum(item.getOutQuantity());
                log.setOperationAfterCount(surplusCount - item.getOutQuantity());
                log.setCreateBy("admin");
                log.setCreateTime(LocalDateTime.now());
                logMapper.insert(log);
            }
            category.setSurplusCount(newsurplusCount);
            categoryMapper.updateById(category);
        }
    }

    @Override
    public Page<ComingOutVO> comingOutLog(ComingOutLogRequest request) {

        Page<ComingOutVO> page = new Page<>();
        page.setSize(request.getPageSize());
        page.setCurrent(request.getPageNum());

        List<Long> subCategoryIds = null;

        if (request.getCategoryId() != null) {
            Long categoryId = request.getCategoryId();
            Category category = getCategoryById(categoryId);
            if (category == null) {
                throw new RuntimeException("分类不存在");
            }

            if (category.getParentId() == 0L) {
                subCategoryIds = categoryMapper.selectAllSubCategoryIds(categoryId);
            } else {
                subCategoryIds = Collections.singletonList(categoryId);
            }
        }

        Page<ComingOutVO> resultPage = logMapper.selectComingOutLog(
                page,
                request.getStartTime(),
                request.getEndTime(),
                subCategoryIds
        );

        // 预加载所有相关分类（包括父分类）
        preloadRelatedCategories(resultPage.getRecords());

        // 为每条记录设置分类路径
        for (ComingOutVO vo : resultPage.getRecords()) {
            if (vo.getCategoryId() != null) {
                vo.setParentName(generateCategoryPath(vo.getCategoryId()));
            }
        }

        return resultPage;
    }
    // 预加载所有相关分类（包括父分类）
    private void preloadRelatedCategories(List<ComingOutVO> records) {
        Set<Long> allCategoryIds = new HashSet<>();

        // 收集所有分类ID
        for (ComingOutVO vo : records) {
            if (vo.getCategoryId() != null) {
                allCategoryIds.add(vo.getCategoryId());
            }
        }

        // 递归收集所有父分类ID
        Set<Long> parentIds = new HashSet<>();
        for (Long categoryId : allCategoryIds) {
            collectParentIds(categoryId, parentIds);
        }
        allCategoryIds.addAll(parentIds);

        // 批量加载所有需要的分类
        if (!allCategoryIds.isEmpty()) {
            List<Category> categories = categoryMapper.selectBatchIds(allCategoryIds);
            for (Category category : categories) {
                categoryCache.put(category.getId(), category);
            }
        }
    }
    // 递归收集父分类ID
    private void collectParentIds(Long categoryId, Set<Long> parentIds) {
        if (categoryId == null || categoryId == 0L) return;

        Category category = getCategoryById(categoryId);
        if (category == null) return;

        Long parentId = category.getParentId();
        if (parentId != null && parentId != 0L && !parentIds.contains(parentId)) {
            parentIds.add(parentId);
            collectParentIds(parentId, parentIds);
        }
    }

    // 递归生成分类路径
    private String generateCategoryPath(Long categoryId) {
        List<String> pathNames = new ArrayList<>();
        Long currentId = categoryId;

        while (currentId != null && currentId != 0L) {
            Category category = getCategoryById(currentId);
            if (category == null) break;

            pathNames.add(category.getName());
            currentId = category.getParentId();
        }

        Collections.reverse(pathNames);
        return String.join(" > ", pathNames);
    }



    @Override
    public List<CategorySearchResult> searchCategories(String keyword) {
        if (StringUtils.isEmpty(keyword)) {
            return Collections.emptyList();
        }

        // 1. 查询匹配的分类
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Category::getName, keyword);
        List<Category> categories = categoryMapper.selectList(queryWrapper);

        if (CollectionUtils.isEmpty(categories)) {
            return Collections.emptyList();
        }
        // 2. 获取所有父分类ID
        Set<Long> parentIds = categories.stream()
                .map(Category::getParentId)
                .filter(parentId -> parentId != null && parentId != 0L)
                .collect(Collectors.toSet());

        // 3. 使用不可变映射解决 lambda final 问题
        final Map<Long, String> parentNameMap = !parentIds.isEmpty()
                ? categoryMapper.selectBatchIds(parentIds)
                .stream()
                .collect(Collectors.toMap(Category::getId, Category::getName))
                : Collections.emptyMap();

        // 4. 构建结果 - 使用不可变映射
        return categories.stream().map(category -> {
            String parentName = null;
            if (category.getParentId() != null && category.getParentId() != 0L) {
                parentName = parentNameMap.get(category.getParentId());
            }

            return new CategorySearchResult(
                    category.getId(),
                    category.getName(),
                    category.getParentId(),
                    parentName
            );
        }).collect(Collectors.toList());


    }

    @Override
    public List<ComingOutVO> getComingOutLogForExport(ComingOutLogQueryParam request) {
        List<Long> subCategoryIds = null;

        if (request.getCategoryId() != null) {
            Long categoryId = request.getCategoryId();
            Category category = getCategoryById(categoryId);
            if (category == null) {
                throw new RuntimeException("分类不存在");
            }

            if (category.getParentId() == 0L) {
                subCategoryIds = categoryMapper.selectAllSubCategoryIds(categoryId);
            } else {
                subCategoryIds = Collections.singletonList(categoryId);
            }
        }

        List<ComingOutVO> resultPage = logMapper.getComingOutLogForExport(
                request.getStartTime(),
                request.getEndTime(),
                subCategoryIds
        );

        // 预加载所有相关分类（包括父分类）
        preloadRelatedCategories(resultPage);

        // 为每条记录设置分类路径
        for (ComingOutVO vo : resultPage) {
            if (vo.getCategoryId() != null) {
                vo.setParentName(generateCategoryPath(vo.getCategoryId()));
            }
        }

        return resultPage;
    }

    // 构建树形结构
    private List<Category> buildTree(List<Category> allNodes) {
        Map<Long, Category> nodeMap = allNodes.stream()
                .collect(Collectors.toMap(Category::getId, Function.identity()));

        List<Category> roots = new ArrayList<>();
        allNodes.forEach(node -> {
            if (node.getParentId().equals(0L)) {
                roots.add(node);
            } else {
                Category parent = nodeMap.get(node.getParentId());
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        });
        return roots;
    }

    // 校验分类名称唯一性
    private void validateCategoryNameUnique(String name, Long parentId) {
        Long count = categoryMapper.selectCount(new QueryWrapper<Category>()
                .eq("name", name)
                .eq("parent_id", parentId)
                .eq("del_flag", "0")
        );
        if (count > 0) {
            throw new RuntimeException("同级分类下名称不能重复");
        }
    }

    // 检查是否存在子分类
    private boolean hasChildren(Long parentId) {
        return categoryMapper.selectCount(new QueryWrapper<Category>()
                .eq("parent_id", parentId)
                .eq("del_flag", "0")
        ) > 0;
    }
}
